import copy
import decimal
import inspect
import json
import re

from my_typing import *
from utils.serializer_utils import settings
from utils.serializer_utils.dateparse import (
    parse_date,
    parse_datetime,
    parse_time,
)
from utils.serializer_utils.exceptions import ValidationError
from utils.serializer_utils.field import (
    Field,
    empty,
    flatten_choices_dict,
    iter_options,
    to_choices_dict,
)
from utils.serializer_utils.utils import humanize_datetime
from utils.serializer_utils.utils.formatting import lazy_format
from utils.serializer_utils.validators import (
    MaxLengthValidator,
    MaxValueValidator,
    MinLengthValidator,
    MinValueValidator,
    ProhibitNullCharactersValidator,
)

TRUE_VALUES = {
    "t", "T",
    "y", "Y", "yes", "YES",
    "true", "True", "TRUE",
    "on", "On", "ON",
    "1", 1,
    True,
}
""" 可以识别为 True 的值 """

FALSE_VALUES = {
    "f", "F",
    "n", "N", "no", "NO",
    "false", "False", "FALSE",
    "off", "Off", "OFF",
    "0", 0, 0.0,
    False,
}
""" 可以识别为 False 的值 """

NULL_VALUES = {
    "null", "Null", "NULL",
    "",
    None,
}
""" 可以识别为 None 的值 """

MAX_STRING_LENGTH: int = 1000
""" 最大的字符串长度（防范恶意字符串输入） """


class BooleanField(Field):
    """ 布尔值 字段 """

    default_error_messages = {
        "invalid": "请输入有效的布尔值",
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的布尔值",
    }

    initial = False

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
        """

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

    def to_internal_value(self, data) -> BoolOrNone:
        try:
            if data in TRUE_VALUES:
                return True

            elif data in FALSE_VALUES:
                return False

            elif (
                data in NULL_VALUES
                and self.allow_null
            ):
                return None

        except TypeError:  # 输入是不可哈希的类型
            pass

        self.fail("invalid", input=data)

    def to_representation(self, value) -> BoolOrNone:
        if value in TRUE_VALUES:
            return True

        elif value in FALSE_VALUES:
            return False

        if (
            value in NULL_VALUES
            and self.allow_null
        ):
            return None

        return bool(value)


class NullBooleanField(Field):
    """ 布尔值（允许为空） 字段 """

    default_error_messages = {
        "invalid": "请输入有效的布尔值",
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的布尔值",
    }

    initial = None

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
        """

        assert "allow_null" not in kwargs, "`allow_null` is not a valid option."

        kwargs["allow_null"] = True

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default

        super().__init__(**kwargs)

    def to_internal_value(self, data) -> BoolOrNone:
        try:
            if data in TRUE_VALUES:
                return True

            elif data in FALSE_VALUES:
                return False

            elif data in NULL_VALUES:
                return None

        except TypeError:  # 输入是不可哈希的类型
            pass

        self.fail("invalid", input=data)

    def to_representation(self, value) -> BoolOrNone:
        if value in NULL_VALUES:
            return None

        if value in TRUE_VALUES:
            return True

        elif value in FALSE_VALUES:
            return False

        return bool(value)


# String types...

class CharField(Field):
    """ 字符串 字段 """

    default_error_messages = {
        "invalid": "请输入有效的字符串",
        "blank": " 该字段不能为空",
        "max_length": "确保该字段不超过{max_length}个字符.",
        "min_length": "确保该字段至少有{min_length}个字符.",
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的字符串",
        "blank": " {label}不能为空",
        "max_length": "{label}最大为{max_length}个字符",
        "min_length": "{label}至少有{min_length}个字符",
    }

    initial = ""

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        allow_blank: bool = False,
        trim_whitespace: bool = False,
        min_length: IntOrNone = None,
        max_length: IntOrNone = None,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            allow_blank: 是否允许为空白
            trim_whitespace: 去除两边的空格
            min_length: 最小长度
            max_length: 最大长度
        """

        self.allow_blank: bool = allow_blank
        self.trim_whitespace: bool = trim_whitespace
        self.min_length: IntOrNone = min_length
        self.max_length: IntOrNone = max_length

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

        if self.max_length is not None:
            message = lazy_format(self.error_messages["max_length"], max_length=self.max_length, label=self.label)
            self.validators.append(MaxLengthValidator(self.max_length, message=message))

        if self.min_length is not None:
            message = lazy_format(self.error_messages["min_length"], min_length=self.min_length, label=self.label)
            self.validators.append(MinLengthValidator(self.min_length, message=message))

        # ProhibitNullCharactersValidator is None on Django < 2.0
        if ProhibitNullCharactersValidator is not None:
            self.validators.append(ProhibitNullCharactersValidator())

    def run_validation(self, data=empty) -> StrOrNone:
        # 此处测试空字符串，以便它不会被验证，并且子类不需要在 `to_internal_value()` 方法中显式处理它
        if (
            data == ""
            or (
                self.trim_whitespace
                and str(data).strip() == ""
            )
        ):
            if not self.allow_blank:
                self.fail("blank")

            return ""

        return super().run_validation(data)

    def to_internal_value(self, data) -> str:
        # 我们宽松地允许将基本数字强制转换为字符串，但其他类型应该失败
        # 例如：不清楚布尔值是否应该表示为 `true` 或 `True` ，并且诸如列表之类的组合可能是用户错误
        if (
            isinstance(data, bool)
            or not isinstance(data, (str, int, float))
        ):
            self.fail("invalid", input=data)

        value = str(data)

        return (
            value.strip()
            if self.trim_whitespace
            else value
        )

    def to_representation(self, value) -> str:
        return str(value)


# Number types...

class IntegerField(Field):
    """ 整数 字段 """

    default_error_messages = {
        "invalid": "请输入有效的整数",
        "max_value": "确保该值小于或等于 {max_value}",
        "min_value": "确保该值大于或等于 {min_value}",
        "max_string_length": "字符串值太大"
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的整数",
        "max_value": "{label}必须 <= {max_value}",
        "min_value": "{label}必须 >= {min_value}",
        "max_string_length": "{label}字符串过长"
    }

    re_decimal = re.compile(r"\.0*\s*$")  # allow e.g. "1.0" as an int, but not "1.2"

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        min_value: IntOrNone = None,
        max_value: IntOrNone = None,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            min_value: 最小值
            max_value: 最大值
        """

        self.min_value: IntOrNone = min_value
        self.max_value: IntOrNone = max_value

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

        if self.max_value is not None:
            message = lazy_format(self.error_messages["max_value"], max_value=self.max_value, label=self.label)
            self.validators.append(MaxValueValidator(self.max_value, message=message))

        if self.min_value is not None:
            message = lazy_format(self.error_messages["min_value"], min_value=self.min_value, label=self.label)
            self.validators.append(MinValueValidator(self.min_value, message=message))

    def to_internal_value(self, data) -> int:
        if (
            isinstance(data, str)
            and len(data) > MAX_STRING_LENGTH
        ):
            self.fail("max_string_length")

        try:
            data = int(self.re_decimal.sub("", str(data)))

        except (ValueError, TypeError):
            self.fail("invalid", input=data)

        return data

    def to_representation(self, value) -> int:
        return int(value)


class FloatField(Field):
    """ 浮点型 字段 """

    default_error_messages = {
        "invalid": "请输入有效的数字/小数",
        "max_value": "确保该值小于或等于 {max_value}",
        "min_value": "确保该值大于或等于 {min_value}",
        "max_string_length": "字符串过长"
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的数字/小数",
        "max_value": "{label}必须 <= {max_value}",
        "min_value": "{label}必须 >= {min_value}",
        "max_string_length": "{label}字符串过长"
    }

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        min_value: IntOrNone = None,
        max_value: IntOrNone = None,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            min_value: 最小长度
            max_value: 最大长度
        """

        self.min_value: IntOrNone = min_value
        self.max_value: IntOrNone = max_value

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

        if self.max_value is not None:
            message = lazy_format(self.error_messages["max_value"], max_value=self.max_value, label=self.label)
            self.validators.append(MaxValueValidator(self.max_value, message=message))

        if self.min_value is not None:
            message = lazy_format(self.error_messages["min_value"], min_value=self.min_value, label=self.label)
            self.validators.append(MinValueValidator(self.min_value, message=message))

    def to_internal_value(self, data) -> float:
        if (
            isinstance(data, str)
            and len(data) > MAX_STRING_LENGTH
        ):
            self.fail("max_string_length")

        try:
            return float(data)

        except (TypeError, ValueError):
            self.fail("invalid", input=data)

    def to_representation(self, value) -> float:
        return float(value)


class DecimalField(Field):
    """ 小数 字段 """

    default_error_messages = {
        "invalid": "请输入有效的数字/小数",
        "max_value": "确保该值小于或等于 {max_value}",
        "min_value": "确保该值大于或等于 {min_value}",
        "max_digits": "确保不超过 {max_digits} 个数字",
        "max_decimal_places": "确保不超过 {max_decimal_places} 位小数",
        "max_whole_digits": "确保小数点前不超过 {max_whole_digits} 位数",
        "max_string_length": "字符串过长"
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值 `{input}` 不是有效的数字/小数",
        "max_value": "{label}必须 <= {max_value}",
        "min_value": "{label}必须 >= {min_value}",
        "max_digits": "{label}最大为 {max_digits} 个数字",
        "max_decimal_places": "{label}不允许超过 {max_decimal_places} 位小数",
        "max_whole_digits": "{label}小数点前不允许超过 {max_whole_digits} 位数",
        "max_string_length": "{label}字符串过长"
    }

    def __init__(
        self,
        label: str,
        max_digits: int,
        decimal_places: int,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        coerce_to_string: bool = None,
        max_value: NumberType = None,
        min_value: NumberType = None,
        rounding: str = None,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            max_digits: 最多有几位数（包括小数点前后的位数）
            decimal_places: 小数点后的位数
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            coerce_to_string: 是否将输入的数字强制转换为字符串类型
            max_value: 允许的最大值（None 表示无限制）
            min_value: 允许的最小值（None 表示无限制）
            rounding: 指定舍入方式
        """

        self.min_value = min_value
        self.max_value = max_value
        self.max_digits = max_digits
        self.decimal_places = decimal_places

        if coerce_to_string is not None:
            self.coerce_to_string = coerce_to_string

        if (
            self.max_digits is not None
            and self.decimal_places is not None
        ):
            self.max_whole_digits = self.max_digits - self.decimal_places

        else:
            self.max_whole_digits = None

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

        if self.max_value is not None:
            message = lazy_format(self.error_messages["max_value"], max_value=self.max_value, label=self.label)
            self.validators.append(MaxValueValidator(self.max_value, message=message))

        if self.min_value is not None:
            message = lazy_format(self.error_messages["min_value"], min_value=self.min_value, label=self.label)
            self.validators.append(MinValueValidator(self.min_value, message=message))

        if rounding is not None:
            valid_roundings = [
                v
                for k, v in vars(decimal).items()
                if k.startswith("ROUND_")
            ]
            assert rounding in valid_roundings, (
                "Invalid rounding option %s. Valid values for rounding are: %s" % (rounding, valid_roundings))

        self.rounding = rounding

    def to_internal_value(self, data) -> Decimal:
        """ 验证输入是否是一个小数，并返回一个 Decimal 实例 """

        data = str(data).strip()

        if len(data) > MAX_STRING_LENGTH:
            self.fail("max_string_length")

        try:
            value = Decimal(data)

        except DecimalException:
            self.fail("invalid", input=data)

        if value.is_nan():  # noqa
            self.fail("invalid", input=data)

        # 检查`正无穷`和`负无穷`
        if value in (Decimal("Inf"), Decimal("-Inf")):
            self.fail("invalid", input=data)

        return self.quantize(self.validate_precision(value))

    def validate_precision(self, value: Decimal) -> Decimal:
        """
        确保不超过数字中的 max_digits 位数，且小数点后不超过 decimal_places 位

        重写此方法以禁用输入值的精度验证或以您需要的任何方式增强它
        """

        sign, digittuple, exponent = value.as_tuple()  # noqa

        if exponent >= 0:
            # 1234500.0
            total_digits = len(digittuple) + exponent
            whole_digits = total_digits
            decimal_places = 0

        elif len(digittuple) > abs(exponent):
            # 123.45
            total_digits = len(digittuple)
            whole_digits = total_digits - abs(exponent)
            decimal_places = abs(exponent)

        else:
            # 0.001234
            total_digits = abs(exponent)
            whole_digits = 0
            decimal_places = total_digits

        if (
            self.max_digits is not None
            and total_digits > self.max_digits
        ):
            self.fail("max_digits", max_digits=self.max_digits)

        if (
            self.decimal_places is not None
            and decimal_places > self.decimal_places
        ):
            self.fail("max_decimal_places", max_decimal_places=self.decimal_places)

        if (
            self.max_whole_digits is not None
            and whole_digits > self.max_whole_digits
        ):
            self.fail("max_whole_digits", max_whole_digits=self.max_whole_digits)

        return value

    def to_representation(self, value) -> Decimal | str:
        coerce_to_string = getattr(self, "coerce_to_string", False)

        if not isinstance(value, Decimal):
            value = Decimal(str(value).strip())

        quantized = self.quantize(value)

        if not coerce_to_string:
            return quantized

        return "{:f}".format(quantized)

    def quantize(self, value) -> Decimal:
        """ 将小数量化为配置的精度 """

        if self.decimal_places is None:
            return value

        context = decimal.getcontext().copy()
        if self.max_digits is not None:
            context.prec = self.max_digits  # noqa

        return value.quantize(
            Decimal(".1") ** self.decimal_places,
            rounding=self.rounding,
            context=context
        )


# Date & time fields...

class DateTimeField(Field):
    """ 日期时间 字段 """

    default_error_messages = {
        "invalid": "日期时间格式错误，请改用以下格式之一: {format}.",
        "date": "应该是 datetime 格式，而不是 date 格式",
        "make_aware": "时区的 datetime 无效 {timezone}",
        "overflow": "datetime 超出范围"
    }

    default_error_messages_with_label = {
        "invalid": "{label}格式错误，请改用以下格式之一: {format}.",
        "date": "{label}应该是 datetime 格式，而不是 date 格式",
        "make_aware": "{label}时区的 datetime 无效 {timezone}",
        "overflow": "{label}的 datetime 超出范围"
    }

    datetime_parser = datetime.datetime.strptime

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        format: str = empty,  # noqa
        input_formats: ListStr = None,
        default_timezone=None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            format: 指定日期时间字符串的格式，如 "%Y-%m-%d %H:%M:%S" （默认为 None，表示使用 `ISO-8601` 格式）
            input_formats: 反序列化时解析输入字符串的日期时间格式列表
            default_timezone: 指定默认时区（例如：pytz.timezone("Asia/Shanghai")）
        """

        if format is not empty:
            self.format = format

        if input_formats is not None:
            self.input_formats = input_formats

        if default_timezone is not None:
            self.timezone = default_timezone

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)

    @staticmethod
    def enforce_timezone(value: datetime.datetime) -> datetime.datetime:
        """
        当 `self.default_timezone` 为 `None` 时，始终返回原始日期时间
        当 `self.default_timezone` 不是 `None` 时，始终返回已知的日期时间
        """

        return value

    def default_timezone(self) -> None:  # noqa
        return None

    def to_internal_value(self, value) -> datetime.datetime:
        input_formats = getattr(self, "input_formats", settings.DATETIME_INPUT_FORMATS)

        if (
            isinstance(value, datetime.date)
            and not isinstance(value, datetime.datetime)
        ):
            self.fail("date")

        if isinstance(value, datetime.datetime):
            return self.enforce_timezone(value)

        for input_format in input_formats:
            if input_format.lower() == settings.ISO_8601:
                try:
                    parsed = parse_datetime(value)

                    if parsed is not None:
                        return self.enforce_timezone(parsed)

                except (ValueError, TypeError):
                    pass

            else:
                try:
                    parsed = self.datetime_parser(value, input_format)  # noqa

                    return self.enforce_timezone(parsed)

                except (ValueError, TypeError):
                    pass

        humanized_format = humanize_datetime.datetime_formats(input_formats)
        self.fail("invalid", format=humanized_format)

    def to_representation(self, value) -> StrOrNone:
        if not value:
            return None

        output_format: StrOrNone = getattr(self, "format", settings.DATETIME_FORMAT)

        if (
            output_format is None
            or isinstance(value, str)
        ):
            return value

        value = self.enforce_timezone(value)

        if output_format.lower() == settings.ISO_8601:
            value = value.isoformat()

            if value.endswith("+00:00"):
                value = value[:-6] + "Z"

            return value

        return value.strftime(output_format)


class DateField(Field):
    """ 日期 字段 """

    default_error_messages = {
        "invalid": "日期格式错误，请改用其中一种格式: {format}.",
        "datetime": "应该是 date 格式，而不是 datetime 格式",
    }

    default_error_messages_with_label = {
        "invalid": "{label}格式错误，请改用其中一种格式: {format}.",
        "datetime": "{label}应该是 date 格式，而不是 datetime 格式",
    }

    datetime_parser = datetime.datetime.strptime

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        format: str = empty,  # noqa
        input_formats: ListStr = None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            format: 指定日期时间字符串的格式，如 "%Y-%m-%d %H:%M:%S" （默认为 None，表示使用 `ISO-8601` 格式）
            input_formats: 反序列化时解析输入字符串的日期时间格式列表
        """

        if format is not empty:
            self.format = format

        if input_formats is not None:
            self.input_formats = input_formats

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)

    def to_internal_value(self, value) -> datetime.date:
        input_formats: StrOrNone = getattr(self, "input_formats", settings.DATE_INPUT_FORMATS)

        if isinstance(value, datetime.datetime):
            self.fail("datetime")

        if isinstance(value, datetime.date):
            return value

        for input_format in input_formats:
            if input_format.lower() == settings.ISO_8601:
                try:
                    parsed = parse_date(value)

                except (ValueError, TypeError):
                    pass

                else:
                    if parsed is not None:
                        return parsed
            else:
                try:
                    parsed = self.datetime_parser(value, input_format)

                except (ValueError, TypeError):
                    pass

                else:
                    return parsed.date()

        humanized_format = humanize_datetime.date_formats(input_formats)
        self.fail("invalid", format=humanized_format)

    def to_representation(self, value) -> StrOrNone:
        if not value:
            return None

        output_format = getattr(self, "format", settings.DATE_FORMAT)

        if (
            output_format is None
            or isinstance(value, str)
        ):
            return value

        # 将 `DateField` 应用于日期时间值几乎总是不明智的事情，因为这意味着天真地删除任何显式或隐式时区信息
        assert not isinstance(value, datetime.datetime), (
            "Expected a `date`, but got a `datetime`. Refusing to coerce, "
            "as this may mean losing timezone information. Use a custom "
            "read-only field and deal with timezone issues explicitly."
        )

        if output_format.lower() == settings.ISO_8601:  # noqa
            return value.isoformat()

        return value.strftime(output_format)


class TimeField(Field):
    """ 时间 字段 """

    default_error_messages = {
        "invalid": "时间格式错误，请改用其中一种格式: {format}.",
    }

    default_error_messages_with_label = {
        "invalid": "{label}格式错误，请改用其中一种格式: {format}.",
    }

    datetime_parser = datetime.datetime.strptime

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        format: str = empty,  # noqa
        input_formats: ListStr = None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            format: 指定日期时间字符串的格式，如 "%Y-%m-%d %H:%M:%S" （默认为 None，表示使用 `ISO-8601` 格式）
            input_formats: 反序列化时解析输入字符串的日期时间格式列表
        """

        if format is not empty:
            self.format = format

        if input_formats is not None:
            self.input_formats = input_formats

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)

    def to_internal_value(self, value) -> datetime.time:
        input_formats: StrOrNone = getattr(self, "input_formats", settings.TIME_INPUT_FORMATS)

        if isinstance(value, datetime.time):
            return value

        for input_format in input_formats:
            if input_format.lower() == settings.ISO_8601:
                try:
                    parsed = parse_time(value)

                except (ValueError, TypeError):
                    pass

                else:
                    if parsed is not None:
                        return parsed
            else:
                try:
                    parsed = self.datetime_parser(value, input_format)

                except (ValueError, TypeError):
                    pass

                else:
                    return parsed.time()

        humanized_format = humanize_datetime.time_formats(input_formats)
        self.fail("invalid", format=humanized_format)

    def to_representation(self, value):
        if value in (None, ""):
            return None

        output_format: StrOrNone = getattr(self, "format", settings.TIME_FORMAT)

        if (
            output_format is None
            or isinstance(value, str)
        ):
            return value

        # 将 `TimeField` 应用于日期时间值几乎总是不明智的事情，因为这意味着天真地删除任何显式或隐式时区信息
        assert not isinstance(value, datetime.datetime), (
            "Expected a `time`, but got a `datetime`. Refusing to coerce, "
            "as this may mean losing timezone information. Use a custom "
            "read-only field and deal with timezone issues explicitly."
        )

        if output_format.lower() == settings.ISO_8601:  # noqa
            return value.isoformat()

        return value.strftime(output_format)


# Choice types...

class ChoiceField(Field):
    """ 选项 字段 """

    default_error_messages = {
        "invalid_choice": "{input} 不是一个有效的选择",
    }

    default_error_messages_with_label = {
        "invalid_choice": "{label}的值 `{input}` 不是一个有效的选择",
    }

    html_cutoff = None

    html_cutoff_text = "More than {count} items..."

    def __init__(
        self,
        choices,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        allow_blank: bool = False,
        **kwargs,
    ) -> None:
        """
        Args:
            choices: 枚举类选项
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            allow_blank: 是否允许为空字符串
        """

        self.choices = choices
        self.allow_blank = allow_blank

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

    def to_internal_value(self, data) -> str:
        if (
            data == ""
            and self.allow_blank
        ):
            return ""

        try:
            return self.choice_strings_to_values[str(data)]

        except KeyError:
            self.fail("invalid_choice", input=data)

    def to_representation(self, value) -> str:
        if value in ("", None):
            return value

        return self.choice_strings_to_values.get(str(value), value)

    def iter_options(self):
        """ 用于渲染选择小部件的模板的辅助方法 """

        return iter_options(
            self.grouped_choices,
            cutoff=self.html_cutoff,
            cutoff_text=self.html_cutoff_text
        )

    def _get_choices(self):
        return self._choices

    def _set_choices(self, choices):
        self.grouped_choices = to_choices_dict(choices)
        self._choices = flatten_choices_dict(self.grouped_choices)

        # 将选项的字符串表示形式映射到基础值
        # 允许我们处理例如：整数选择，同时支持整数或字符串输入，但仍然可以获得正确的数据类型
        self.choice_strings_to_values = {
            str(key): key
            for key in self.choices
        }

    choices = property(_get_choices, _set_choices)


# File types...

class FileField(Field):
    """ 文件 字段 """

    default_error_messages = {
        "required": "请提交文件",
        "invalid": "提交的数据不是文件，请检查表单上的编码类型",
        "no_name": "无法确定文件名",
        "empty": "已提交文件为空",
        "max_length": "确保该文件名最多有 {max_length} 个字符 (当前为 {length}).",
    }

    default_error_messages_with_label = {
        "required": "请提交{label}",
        "invalid": "提交的{label}数据不是文件，请检查表单上的编码类型",
        "no_name": "无法确定{label}的文件名",
        "empty": "已提交的{label}文件为空",
        "max_length": "确保该{label}的文件名最多有 {max_length} 个字符 (当前为 {length}).",
    }

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        allow_empty_file: bool = False,
        max_length: IntOrNone = None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            min_value: 最小长度
            max_value: 最大长度
        """

        self.max_length = max_length
        self.allow_empty_file = allow_empty_file

        if "use_url" in kwargs:
            self.use_url = kwargs.pop("use_url")

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)

    def to_internal_value(self, data):
        try:
            # UploadedFile 对象应具有 `name` 和 `size` 属性
            file_name = data.name
            file_size = data.size

        except AttributeError:
            self.fail("invalid")

        if not file_name:  # noqa
            self.fail("no_name")

        if (
            not self.allow_empty_file
            and not file_size  # noqa
        ):
            self.fail("empty")

        if (
            self.max_length
            and len(file_name) > self.max_length
        ):
            self.fail("max_length", max_length=self.max_length, length=len(file_name))

        return data

    def to_representation(self, value) -> StrOrNone:
        if not value:
            return None

        return value.name


# Composite field types...

class _UnvalidatedField(Field):
    """ 未验证 字段（内部使用） """

    def __init__(self, *args, **kwargs) -> None:
        super().__init__(*args, **kwargs)
        self.allow_blank = True
        self.allow_null = True

    def to_internal_value(self, data):
        return data

    def to_representation(self, value):
        return value


class ListField(Field):
    """ 列表 字段 """

    child = _UnvalidatedField()

    initial = []

    default_error_messages = {
        "not_a_list": "应该是 list 格式，而不是 {input_type} 格式",
        "empty": "该列表不能为空",
        "min_length": "确保该字段至少有{min_length}个元素",
        "max_length": "确保该字段不超过{max_length}个元素"
    }

    default_error_messages_with_label = {
        "not_a_list": "{label}应该是 list 格式，而不是 {input_type} 格式",
        "empty": "{label}列表不能为空",
        "min_length": "{label}至少有{min_length}个元素",
        "max_length": "{label}最多为{max_length}个元素"
    }

    def __init__(
        self,
        label: str,
        child=None,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        allow_empty: bool = True,
        min_length: IntOrNone = None,
        max_length: IntOrNone = None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            child: 子元素的序列化器
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            allow_empty: 是否允许为空列表
            min_value: 最小长度
            max_value: 最大长度
        """

        self.child = child or copy.deepcopy(self.child)
        self.allow_empty = allow_empty
        self.min_length = min_length
        self.max_length = max_length

        assert not inspect.isclass(self.child), "`child` has not been instantiated."
        assert self.child.source is None, (
            "The `source` argument is not meaningful when applied to a `child=` field. "
            "Remove `source=` from the field declaration."
        )

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)
        self.child.bind(field_name="", parent=self)

        if self.max_length is not None:
            message = lazy_format(self.error_messages["max_length"], max_length=self.max_length, label=self.label)
            self.validators.append(MaxLengthValidator(self.max_length, message=message))

        if self.min_length is not None:
            message = lazy_format(self.error_messages["min_length"], min_length=self.min_length, label=self.label)
            self.validators.append(MinLengthValidator(self.min_length, message=message))

    def get_value(self, dictionary):
        if (
            self.field_name not in dictionary
            and getattr(self.root, "partial", False)
        ):
            return empty

        return dictionary.get(self.field_name, empty)

    def to_internal_value(self, data) -> list:
        """ 由基本数据类型组成的字典列表 -> 由本地值（Python 内置的数据类型）组成的字典列表 """

        if (
            isinstance(data, (str, Mapping))
            or not hasattr(data, "__iter__")
        ):
            self.fail("not_a_list", input_type=type(data).__name__)

        if (
            not self.allow_empty
            and len(data) == 0
        ):
            self.fail("empty")

        return self.run_child_validation(data)

    def to_representation(self, data) -> list:
        """ 由本地值（Python 内置的数据类型）组成的字典列表 -> 由基本数据类型组成的字典列表 """

        return [
            (
                self.child.to_representation(item)
                if item is not None
                else None
            )
            for item in data
        ]

    def run_child_validation(self, data) -> list:
        result = []
        errors = OrderedDict()  # noqa

        for idx, item in enumerate(data):
            try:
                result.append(self.child.run_validation(item))

            except ValidationError as e:
                errors[idx] = e.detail

        if not errors:
            return result

        raise ValidationError(errors)


class DictField(Field):
    """ 字段 字段 """

    child = _UnvalidatedField()

    initial = {}

    default_error_messages = {
        "not_a_dict": "应该是 dict 格式，而不是 {input_type} 格式",
        "empty": "该字典不能为空",
    }

    default_error_messages_with_label = {
        "not_a_dict": "{label}应该是 dict 格式，而不是 {input_type} 格式",
        "empty": "{label}字典不能为空",
    }

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
        """

        self.child = kwargs.pop("child", copy.deepcopy(self.child))
        self.allow_empty = kwargs.pop("allow_empty", True)

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        assert not inspect.isclass(self.child), "`child` has not been instantiated."
        assert self.child.source is None, (
            "The `source` argument is not meaningful when applied to a `child=` field. "
            "Remove `source=` from the field declaration."
        )

        super().__init__(*args, **kwargs)
        self.child.bind(field_name="", parent=self)

    def to_internal_value(self, data) -> dict:
        """ 由基本数据类型组成的字典 -> 由本地值（Python 内置的数据类型）组成的字典 """

        if not isinstance(data, dict):
            self.fail("not_a_dict", input_type=type(data).__name__)

        if (
            not self.allow_empty
            and len(data) == 0
        ):
            self.fail("empty")

        return self.run_child_validation(data)

    def to_representation(self, value) -> dict:
        return {
            str(key): (
                self.child.to_representation(val)
                if val is not None
                else None
            )
            for key, val in value.items()
        }

    def run_child_validation(self, data) -> dict:
        result = {}
        errors = OrderedDict()  # noqa

        for key, value in data.items():
            key = str(key)

            try:
                result[key] = self.child.run_validation(value)

            except ValidationError as e:
                errors[key] = e.detail

        if not errors:
            return result

        raise ValidationError(errors)


class JSONField(Field):
    """ JSON 字符串 字段 """

    default_error_messages = {
        "invalid": "请输入有效的 JSON"
    }

    default_error_messages_with_label = {
        "invalid": "{label}的值不是有效的 JSON"
    }

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        binary: bool = False,
        encoder=None,
        *args,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            binary: 二进制的内容
            encoder: 自定义解码器
        """

        self.binary: bool = binary
        self.encoder = encoder

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(*args, **kwargs)

    def to_internal_value(self, data) -> Union[str, bytes]:
        try:
            if self.binary or getattr(data, "is_json_string", False):
                if isinstance(data, bytes):
                    data = data.decode()

                return json.loads(data)

            else:
                json.dumps(data, cls=self.encoder)

        except (TypeError, ValueError):
            self.fail("invalid")

        return data

    def to_representation(self, value) -> Union[str, bytes]:
        if self.binary:
            value = json.dumps(value, cls=self.encoder)
            value = value.encode()

        return value


# Miscellaneous field types...

class SerializerMethodField(Field):
    """
    A read-only field that get its representation from calling a method on the parent serializer class.
    调用的方法的形式为 `get_{field_name}`，并且应该采用单个参数，即正在序列化的对象

    例子：

    >>> class ExampleSerializer(self):
    ...     extra_info = SerializerMethodField()
    ...
    ...     def get_extra_info(self, obj):
    ...         return ...  # 计算一些要返回的数据
    """

    def __init__(
        self,
        label: str,
        required: bool = True,
        default: str = empty,
        allow_null: bool = False,
        method_name: str = None,
        **kwargs,
    ) -> None:
        """
        Args:
            label: 字段名
            required: 是否必填
            default: 默认值
            allow_null: 是否允许为空
            method_name: 方法名
        """

        self.method_name = method_name

        kwargs["source"] = "*"
        kwargs["read_only"] = True

        kwargs["label"] = label
        kwargs["required"] = required
        kwargs["default"] = default
        kwargs["allow_null"] = allow_null

        super().__init__(**kwargs)

    def bind(self, field_name, parent):
        # 为了强制执行一致的样式，如果使用了多余的 `method_name` 参数，我们会出错
        # 例如:
        #   my_field = serializer.SerializerMethodField(method_name="get_my_field")
        default_method_name = "get_{field_name}".format(field_name=field_name)

        # 方法名称应默认为 `get_{field_name}`
        if self.method_name is None:
            self.method_name = default_method_name

        super().bind(field_name, parent)

    def to_representation(self, value):
        method = getattr(self.parent, self.method_name)
        return method(value)
